package crud.client.factory.form.multiple.value;

import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.IsSerializable;
import com.smartgwt.client.data.Record;
import com.smartgwt.client.widgets.form.fields.FormItem;

import crud.client.data.Colonne;
import crud.client.data.DataView;
import crud.client.data.Donnee;
import crud.client.dialog.TableListGrid;
import crud.client.event.ColumnInitEvent;
import crud.client.factory.form.FormItemFactory;
import crud.client.util.GenericCallback;

public abstract class MultipleValueFormItemFactory extends FormItemFactory implements Serializable, IsSerializable
{
	public abstract FormItem newMultipleFormItem(Colonne colonne);
	public abstract void populateList(Colonne colonne, AsyncCallback<List<DataView>> callback);

	protected Map<String, DataView> dataViewMap = new LinkedHashMap<String, DataView>();

	@Override
	public void setValueInRecord(final Record record, final TableListGrid tableListGrid, final Donnee donnee)
	{

		// Sauvegarde du libelle de la donnée (pour affichage)
		if (donnee.getDataView().getKey() != null)
		{
			DataView dataView = dataViewMap.get(donnee.getDataView().getKey());
			if (dataView != null)
			{
				donnee.getDataView().setLabel(dataView.getLabel());
			} 
			record.setAttribute(donnee.getColonne().getCodeColonne(), donnee.getDataView().getLabel());
		}
	}

	@Override
	public FormItem newFormItem(Colonne colonne, DataView dataView)
	{
		final FormItem formItem = newMultipleFormItem(colonne);
		formItem.setRequired(!colonne.isNullable());

		// Ajout de la liste des données dans le FormItem
		if (dataViewMap.values().isEmpty() == false)
		{
			// Pré-selection d'une donnée ??
			if (!colonne.isNullable())
			{
				formItem.setValue(dataViewMap.keySet().iterator().next());
			} 

			// Ajout de la liste des données
			setFormItemValueMap(formItem);
		} 
		
		if (dataView != null && dataView.getKey() != null)
		{
			formItem.setValue(dataView.getKey());
		}

		return formItem;
	}
	
	@Override
	public void initialize(Colonne colonne, final HandlerManager handlerManager, final ColumnInitEvent columnInitEvent)
	{
		AsyncCallback<List<DataView>> dataCallback = new GenericCallback<List<DataView>>()
		{

			@Override
			public void onSuccess(List<DataView> dataViewList)
			{
				for (DataView dataView : dataViewList)
				{
					dataViewMap.put(dataView.getKey(), dataView);
				}
				handlerManager.fireEvent(columnInitEvent);
			}
		};

		populateList(colonne, dataCallback);
	}
	
	@Override
	public String displayValue(String key)
	{
		if (key == null || key.isEmpty())
		{
			return null;
		}
		DataView dataView = dataViewMap.get(key);
		if (dataView == null)
		{
			return null;
		}
		return dataView.getLabel();
	}

	private void setFormItemValueMap(FormItem formItem)
	{
		// Ajout dans la liste
		LinkedHashMap<String, Serializable> dataMap = new LinkedHashMap<String, Serializable>();
		for (DataView dataView : dataViewMap.values())
		{
			dataMap.put(dataView.getKey(), dataView.getLabel());
		}
		formItem.setValueMap(dataMap);
	}

	@Override
	public Serializable getData(Serializable key)
	{
		if (key == null)
		{
			return null;
		}
		DataView dataView = dataViewMap.get(key);
		if (dataView == null)
		{
			return null;
		}
		return dataView.getData();
	}

}
